<template>
  <div class="dock">
    <div class="bubble">
      <slot :toggleOrbit="toggleOrbit"></slot>
    </div>
    <div
      class="half-clip"
      ref="halfClipRef"
      @pointerdown="onPointerDown"
      @pointerup="onPointerUp"
      @pointerleave="onPointerUp"
      @pointermove="onPointerMove"
    >
      <div
        class="orbit"
        :class="{ dragging, expanded }"
        :style="{ transform: `rotate(${theta}deg)` }"
      >
        <div
          v-for="(item, idx) in items"
          :key="item.id"
          class="planet"
          :style="planetStyle(idx)"
          @click="setActive(idx)"
        >
          <div class="planet-inner" :style="innerStyle(idx)">
            <span class="emoji">{{ item.icon }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
const items = ref([
  { id: 1, title: '笔记', icon: '📒' },
  { id: 2, title: '文档', icon: '📑' },
  { id: 3, title: '编译', icon: '⚙️' },
  { id: 4, title: '助手', icon: '🤖' },
  { id: 5, title: '图表', icon: '📊' },
  { id: 6, title: '探索', icon: '🚀' },
  { id: 6, title: '探索', icon: '🚀' }
])

const radius = ref(0) // 初始半径为0（收缩状态）
const targetRadius = ref(50) // 目标半径
const expanded = ref(false) // 展开状态
const stepAngle = computed(() => 360 / items.value.length)
const theta = ref(0)
const activeIndex = ref(0)
let animationFrameId: number | null = null
const emit = defineEmits(['select'])
// const coordinateInformation = computed(async () => {
//   return await window.electron.ipcRenderer.invoke('get-location-information')
// })
const lock = ref(false) //是否第一次被点击

// 切换展开/收缩状态
const toggleOrbit = () => {
  expanded.value = !expanded.value

  if (expanded.value) {
    const list = lock.value ? [90, 90] : [0, 0]
    window.electron.ipcRenderer.invoke('set-window-config', {
      size: [240, 240],
      position: list
    })

    setTimeout(() => {
      whetherToOpenTheTool()
    }, 100)
  } else {
    whetherToOpenTheTool()
    setTimeout(() => {
      window.electron.ipcRenderer.invoke('set-window-config', {
        size: [55, 55],
        position: [-90, -90]
      })
    }, 1000)
  }
  if (!lock.value) {
    setTimeout(() => {
      lock.value = true
    }, 1000)
  }
}
const whetherToOpenTheTool = () => {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
    animationFrameId = null
  }

  const targetR = expanded.value ? targetRadius.value : 0
  // 动画参数
  const duration = 500 // 动画持续时间
  const startTime = performance.now()
  const startR = radius.value
  const animate = (timestamp: number) => {
    const elapsed = timestamp - startTime
    const progress = Math.min(elapsed / duration, 1)

    // 使用缓动函数使动画更自然
    const easeProgress = expanded.value
      ? 1 - Math.pow(1 - progress, 3) // 展开时使用弹性缓动
      : Math.pow(progress, 2) // 收缩时使用减速缓动

    radius.value = startR + (targetR - startR) * easeProgress
    // console.log("参数信息", radius.value);

    if (progress < 1) {
      animationFrameId = requestAnimationFrame(animate)
    } else {
      radius.value = targetR
      animationFrameId = null

      // 如果是展开状态，自动对齐到当前活动项
      if (expanded.value) {
        goTo(activeIndex.value)
      }
    }
  }

  animationFrameId = requestAnimationFrame(animate)
}

const planetStyle = (idx: number) => {
  const angle = idx * stepAngle.value
  return {
    opacity: expanded.value ? '1' : disappearanceCalculation(radius.value),
    transform: `rotate(${angle}deg) translate(${radius.value}px)`,
    transition: 'transform opacity 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55)'
  }
}
const disappearanceCalculation = (r: number) => {
  return r / targetRadius.value
}

const innerStyle = (idx: number) => {
  const angle = idx * stepAngle.value
  return {
    transform: `rotate(${-(theta.value + angle)}deg)`,
    transition: 'transform 0.5s ease'
  }
}

const goTo = (idx: number) => {
  activeIndex.value = idx
  theta.value = -activeIndex.value * stepAngle.value
}

const setActive = (idx: number) => {
  if (velocity !== 0) return
  emit('select', items.value[idx])
}

// 拖拽与惯性滚动逻辑（与之前相同）
const halfClipRef = ref<HTMLElement | null>(null)
let dragging = false
let downAngle = 0
let startTheta = 0
let lastMoveTime = 0
let lastAngle = 0
let velocity = 0
let rafId: number | null = null

const angleDiff = (a: number, b: number) => {
  let d = a - b
  if (d > 180) d -= 360
  if (d < -180) d += 360
  return d
}

const getCenter = () => {
  const el = halfClipRef.value!
  const rect = el.getBoundingClientRect()
  return { cx: rect.left + rect.width / 2, cy: rect.top + rect.height / 2 }
}

const calcAngleFromEvent = (e: PointerEvent) => {
  const { cx, cy } = getCenter()
  const dx = e.clientX - cx
  const dy = e.clientY - cy
  return (Math.atan2(dy, dx) * 180) / Math.PI
}

const onPointerDown = (e: PointerEvent) => {
  if (!expanded.value) return

  dragging = true
  ;(e.target as HTMLElement).setPointerCapture(e.pointerId)
  downAngle = calcAngleFromEvent(e)
  startTheta = theta.value
  lastAngle = downAngle
  lastMoveTime = performance.now()
  velocity = 0

  if (rafId) {
    cancelAnimationFrame(rafId)
    rafId = null
  }
}

const onPointerMove = (e: PointerEvent) => {
  if (!dragging || !expanded.value) return
  const angle = calcAngleFromEvent(e)
  const delta = angleDiff(angle, downAngle)
  theta.value = startTheta + delta

  const now = performance.now()
  const dt = Math.max(1, now - lastMoveTime)
  const diff = angleDiff(angle, lastAngle)
  velocity = diff / dt
  lastAngle = angle
  lastMoveTime = now
}

const snapToNearest = () => {
  const targetIndex = Math.round(-theta.value / stepAngle.value)
  const targetTheta = -targetIndex * stepAngle.value

  const duration = 300
  const startTime = performance.now()
  const startTheta = theta.value
  const deltaTheta = angleDiff(targetTheta, startTheta)

  const animate = () => {
    const now = performance.now()
    const progress = Math.min((now - startTime) / duration, 1)
    const easeProgress = 1 - Math.pow(1 - progress, 3)

    theta.value = startTheta + deltaTheta * easeProgress

    if (progress < 1) {
      rafId = requestAnimationFrame(animate)
    } else {
      theta.value = targetTheta
      activeIndex.value = targetIndex
      rafId = null
    }
  }

  rafId = requestAnimationFrame(animate)
}

const animateInertia = () => {
  const friction = 0.96
  const minVelocity = 0.05

  const step = () => {
    velocity *= friction

    if (Math.abs(velocity) < minVelocity) {
      snapToNearest()
      return
    }

    theta.value += velocity * 16
    rafId = requestAnimationFrame(step)
  }

  rafId = requestAnimationFrame(step)
}

const onPointerUp = () => {
  if (!dragging || !expanded.value) return
  dragging = false

  if (Math.abs(velocity) > 0.5) {
    animateInertia()
  } else {
    snapToNearest()
  }
}

onMounted(() => {
  goTo(0)
})
</script>

<style scoped lang="scss">
.dock {
  position: relative;
  width: 260px;
  height: 260px;
  // border: 1px solid #000;
}
.bubble {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: radial-gradient(
    36px 360px at 60% 60%,
    rgba(255, 255, 255, 0.9),
    rgba(235, 242, 255, 0.6)
  );
  box-shadow: 0 4px 5px rgba(10, 19, 31, 0.08);
  filter: blur(0.2px);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
  z-index: 10;

  &:hover {
    transform: translate(-50%, -50%) scale(1.1);
    box-shadow: 0 6px 8px rgba(10, 19, 31, 0.12);
  }
}

.half-clip {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 240px;
  height: 240px;
  overflow: hidden;
  // border: 1px solid #000;
}

.orbit {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  transform-origin: 0 0;
  transition: transform 400ms cubic-bezier(0.2, 0, 0.1, 1);

  &.expanded {
    .planet {
      opacity: 1;
      pointer-events: auto;
    }
  }

  &:not(.expanded) {
    .planet {
      // opacity: 1;
      pointer-events: none;
    }
  }
}

.planet {
  position: absolute;
  left: 0;
  top: 0;
  width: 50px;
  height: 50px;
  transform-origin: 0 0;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.3s ease,
    transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.planet-inner {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #fff, #e8eeff);
  box-shadow:
    0 6px 12px rgba(41, 111, 255, 0.25),
    inset 0 0 12px rgba(168, 188, 255, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease,
    opacity 0.2s ease;

  &:hover {
    box-shadow:
      0 10px 20px rgba(41, 111, 255, 0.35),
      inset 0 0 14px rgba(168, 188, 255, 1);
    transform: scale(1.08);
  }
}

.emoji {
  font-size: 22px;
  transition: transform 0.3s ease;
}
</style>
